package com.skwyb.form.core;

import com.alibaba.fastjson.JSONObject;
import com.skwyb.form.constants.ResultCode;
import com.skwyb.form.utils.DateUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.stream.Collectors;

@Log4j2
@ControllerAdvice
@Component
public class GlobalExceptionHandler {

    /**
     * json 格式
     *
     * @param ex MethodArgumentNotValidException
     * @return object
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ObjectResult errorHandler(MethodArgumentNotValidException ex) {
        BindingResult result = ex.getBindingResult();
        String errorMsg = result.getFieldErrors().stream().map(r -> r.getField() + r.getDefaultMessage()).collect(Collectors.joining());
        return new ObjectResult(ResultCode.PARAM_ILLEGAL.getCode(), errorMsg);
    }


    /**
     * 表单格式
     *
     * @param ex BindException
     * @return object
     */
    @ExceptionHandler(value = BindException.class)
    public ObjectResult errorHandler(BindException ex) {
        BindingResult result = ex.getBindingResult();
        String errorMsg = result.getFieldErrors().stream().map(r -> r.getField() + r.getDefaultMessage()).collect(Collectors.joining());
        return new ObjectResult(ResultCode.PARAM_ILLEGAL.getCode(), errorMsg);
    }


    /**
     * 业务异常
     *
     * @param e BusinessException
     */
    @ResponseBody
    @ExceptionHandler(value = BusinessException.class)
    public Object allBusinessExceptionHandler(BusinessException e) {
        return new ObjectResult(e.getCode(), e.getMessage());
    }

    /**
     * 未知的异常捕获处理
     *
     * @param exception 统一异常
     * @return Object
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public Object allUnknowExceptionHandler(HttpServletRequest request, Exception exception) {
        if (exception instanceof BusinessException) {
            BusinessException e = (BusinessException) exception;
            return new ObjectResult(e.getCode(), e.getMessage());
        }
        String error = logError(request, exception);
        log.error(error);
        //可以发送邮件通知开发
        return new ObjectResult(ResultCode.FAIL);
    }

    private String logError(HttpServletRequest request, Exception exception) {
        log.error("发生未知异常:", exception);
        StringWriter sw = new StringWriter();
        sw.append(String.format("Date:{%s};\n", DateUtil.getDate()));
        sw.append(String.format("url:{%s}产生错误;\n", request.getRequestURI()));
        sw.append(String.format("请求IP:{%s};\n", request.getRemoteAddr()));
        sw.append(String.format("type:{%s};\n", request.getMethod()));
        sw.append(String.format("请求参数:{%s};\n", JSONObject.toJSONString(request.getParameterMap())));
        exception.printStackTrace(new PrintWriter(sw));
        return sw.toString();
    }
}
